package generate

import (
	"fmt"
	"gorm.io/gen/internal/model"
	"gorm.io/gen/internal/parser"
	"gorm.io/gorm"
	"gorm.io/gorm/utils/tests"
	"regexp"
	"strings"
)

// ZormGetQueryStructMeta generate db model by table name
func ZormGetQueryStructMeta(db *gorm.DB, conf *model.Config) (*QueryStructMeta, []*model.Column, error) {
	if _, ok := db.Config.Dialector.(tests.DummyDialector); ok {
		return nil, nil, fmt.Errorf("UseDB() is necessary to generate model struct [%s] from database table [%s]", conf.ModelName, conf.TableName)
	}

	conf = conf.Preprocess()
	tableName, structName, fileName := conf.GetNames()
	if tableName == "" {
		return nil, nil, nil
	}
	if err := checkZormStructName(structName); err != nil {
		return nil, nil, fmt.Errorf("model name %q is invalid: %w", structName, err)
	}

	columns, err := getTableColumns(db, conf.GetSchemaName(db), tableName, conf.FieldWithIndexTag)
	if err != nil {
		return nil, nil, err
	}
	var pk []*model.Column
	for _, c := range columns {
		isPriKey, ok := c.PrimaryKey()
		isValidPriKey := ok && isPriKey
		if isValidPriKey {
			pk = append(pk, c)
			fmt.Printf("Found Primary Key: %v \n", c)
		}
	}

	return (&QueryStructMeta{
		db:              db,
		Source:          model.Table,
		Generated:       true,
		FileName:        fileName,
		TableName:       tableName,
		TableComment:    getTableComment(db, tableName),
		ModelStructName: structName,
		QueryStructName: uncaptialize(structName),
		S:               strings.ToLower(structName[0:1]),
		StructInfo:      parser.Param{Type: structName, Package: conf.ModelPkg},
		ImportPkgPaths:  conf.ImportPkgPaths,
		Fields:          getFields(db, conf, columns),
	}).addMethodFromAddMethodOpt(conf.GetModelMethods()...), pk, nil
}

// checkZormStructName 检测名称是否符合SQL规范，允许英文、数字、下划线、中文字符
func checkZormStructName(name string) error {
	// 使用正则表达式来匹配允许的字符
	_, err := regexp.MatchString("^[a-zA-Z0-9_\\p{Han}]+$", name)
	if err != nil {
		return fmt.Errorf("model name cannot contains invalid character:%v", err)
	}
	return nil
}
